import { controller, SimulateController } from './Controller';
import { getUid } from "@/util/common";
import { simHttp } from "@/util/httpClient/SimulationHttpClient";
import localFileService from '@/util/SimLocalFile/LocalFileElectron';
import { reactive } from 'vue';
import local from '@/util/local';
import { InfoLevel, LogRecord } from "./_";
import { DebouncedFunc, throttle } from "lodash";

export default class ConsoleService {
  // 日志是否初始化
  isInit = false;

  controller: SimulateController;
  consumeRecord: DebouncedFunc<() => void>

  /** 原始数据 */
  originData: { records: LogRecord[] } = { records: [] };
  /** 过滤后的数据 */
  renderData = reactive({ records: [] }) as { records: LogRecord[] }
  consolesRecord = [] as LogRecord[];
  logLevel = InfoLevel.INFO;
  logLevels?: InfoLevel[];
  showSearch?: boolean;
  searchKey?: string;
  filterStart?: boolean;

  constructor(c: SimulateController) {
    this.controller = c;
    this.consumeRecord = throttle(() => {
      for (let i = 0; i < this.consolesRecord.length; i++) {
        const log = this.consolesRecord[i];
        this.originData.records.push(log);
        this.controller.logFileService.appendLog(log);
        if (this.showLogByFilter(log)) {
          this.renderData.records.push(log);
        }
      }
      if (this.originData.records.length > 900) {
        this.originData.records = this.originData.records.slice(this.originData.records.length - 600);
      }
      if (this.renderData.records.length > 900) {
        this.renderData.records = this.renderData.records.slice(this.renderData.records.length - 600);
      }
      this.consolesRecord.length = 0;
    }, this.controller.customizedTimerGap + 10);
  }

  serviceInit() {
    this.isInit = false;
    this.originData.records.length = 0;
    this.renderData.records.length = 0;
    this.consolesRecord.length = 0;
    // this.addRecord({
    //   level: InfoLevel.INFO,
    //   message: this.controller.locale.localeTrans('init_simulation')
    // });
  }

  clearLog() {
    this.originData.records.length = 0;
    this.renderData.records.length = 0;
  }

  /** 转换导出日志内容格式 */
  convertToString(Obj: LogRecord[]) {
    let result = "";
    Obj.forEach((item: LogRecord, index: number) => {
      result += `${index}>${item.time} ${item.context}\n`;
    });
    return result;
  }

  /** 转换日志控制台显示格式 */
  convertToConsole(Obj: LogRecord) {
    if (Obj.context) {
      return Obj.context;
    }
    
    return `[${Obj.level}] ${Obj.message}`;
  }

  copyLog() {
    try {
      navigator.clipboard.writeText(
        this.convertToString(this.renderData.records)
      );
      app.$notify({
        title: local.localeTrans('copy_succ'),
        type: 'success',
      });
    } catch (error) {
      console.error("Failed to copy: ", error);
    }
  }

  /**
   * 导出所有日志
   */
  exportLog() {
    if (localFileService) {
      let path = localFileService.showSaveDialog({
        title: local.localeTrans('s_f_path'),
        buttonLabel: '选择',
        filters: [{
          name: 'M-Design Project',
          extensions: ['log']
        }]
      });
      if (!path) return;
      else {
        // copy日志文件
        this.controller.logFileService.copyLogsTo(path);
      }
    } else {
      console.log("非 Electron 环境暂未实现");
    }
  }

  submitEmulateText(emulateText: string, langType: string) {

    return new Promise((outer_resolve, outer_reject) => {
      const params = {
        formulas: [
          {
            id: "11111",
            expression: emulateText
          }
        ],
        matlabVersionNO: controller.matlabVersion,
      };

      simHttp.post({
        api: 'matlab/run',
        data: params
      }).then(res => {
        this.addRecord({
          message: res.data.data[0].result,
          level: InfoLevel.INFO,
        });
        outer_resolve(true);
      }).catch(err => {
        outer_reject(err);
      });
    });
  }

  getCurrentTime() {
    // return formatTime(Date.now(), "HH:mm:ss,SSS");
    return this.controller.clockService.simulationTime;
  }

  addRecord(data: LogRecord) {
    if (!data) return;
    if (!this.isInit) {
      this.isInit = true;
    }
    const log = { ...data };
    log.id = log.id || getUid();
    // 日志时间读取仿真时钟时间
    log.time = log.time || this.controller.clockService.simulationTime;
    log.context = this.convertToConsole(log);
    // if (this.filterLogByLevel(this.logLevel, data.level)) {
    this.consolesRecord.push(log);
    // }
    this.consumeRecord();
  }

  private filterLogByLevel(l: InfoLevel, dataLevel: InfoLevel) {
    if (l === InfoLevel.DEBUG) {
      return true;
    } else if (l === InfoLevel.INFO) {
      return [InfoLevel.INFO, InfoLevel.WARN, InfoLevel.ERROR].includes(dataLevel);
    } else if (l === InfoLevel.WARN) {
      return [InfoLevel.WARN, InfoLevel.ERROR].includes(dataLevel);
    } else {
      return dataLevel === InfoLevel.ERROR;
    }
  }

  /**
   * 日志是否显示
   */
  private showLogByFilter(log: LogRecord) {
    // 日志等级
    // if (this.logLevels && this.logLevels.length > 0) {
    //   if (this.logLevels.indexOf(log.level) === -1) {
    //     return false;
    //   }
    // }
    if (this.logLevel && !this.filterLogByLevel(this.logLevel, log.level)) {
      return false;
    }
    if (this.showSearch && this.searchKey && log.context) {
      return log.context.indexOf(this.searchKey) !== -1;
    }
    return true;
  }

  contextExp = /\[(DEBUG|INFO|WARN|ERROR)\]? (.*)/;
  /**
   * 触发筛选
   */
  filterLog() {
    // 从本地文件中查出内容
    const localContent = this.controller.logFileService.getLogContent();
    // 根据换行符拆分
    const arr = localContent.split('\n');
    const records: LogRecord[] = [];
    for (let i = 0; i < arr.length; i++) {
      const it = arr[i];
      if (it) {
        if (it.indexOf(' : ') > -1) {
          const [time, context] = it.split(' : ');
          const match = context.match(this.contextExp);
          if (match && match[1] && match[2]) {
            records.push({
              time,
              context,
              message: match[2],
              level: match[1] as InfoLevel
            });
          }
        } else {
          // 内容存在换行符，需要和前一个日志合并
          const last = records[records.length - 1];
          if (last) {
            last.context += it;
          }
        }
      }
    }
    console.log(records);
    const originLogs = records;
    const logs: LogRecord[] = [];
    for (let i = 0; i < originLogs.length; i++) {
      const log = originLogs[i];
      if (this.showLogByFilter(log)) {
        logs.push(log);
      }
    }
    this.renderData.records = logs;
  }

  /**
   * 清除筛选
   */
  clearFilter() {
    this.searchKey = '';
    this.filterStart = false;
    this.showSearch = false;
    this.filterLog();
  }
}

